package org.puppet.demo.tank.puppet;

import java.util.LinkedList;

import org.puppet.demo.tank.control.BulletController;
import org.puppet.game.World;
import org.puppet.game.element.Puppet;

public abstract class Bullet extends Puppet {

	protected static LinkedList<Double> angels;	
	static{
		angels = new LinkedList<Double>();
		for (double i = 90 - 11.25; i > -90; i -= 22.5) {
			angels.add(Math.tan(Math.toRadians(i)));
		}
	}
	
	protected Tank tank;
	protected Explode explode;
	protected boolean isFaceLeft = false;
	protected int cur;
	protected float aVX;
	
	protected BulletController bulletController;
	
	public Bullet(Tank tank) {
		super();
		this.tank = tank;	
		this.bulletController = new BulletController(this);
	}

	@Override
	public void live() {
		super.live();
		World.current.reg(bulletController);
	}
	
	@Override
	public void die() {
		super.die();
		World.current.getDirector().unreg(bulletController);
	}

	public void updateAnim(long elapsedTime) {
		if(cur < 7 && vY < aVX * angels.get(cur + 1)){
			changeAnimation(++cur);
		}
	}
	
	public void lunch(float avX, float avY) {
		isFaceLeft = avX == 0 ? isFaceLeft : (avX < 0);
		this.x = tank.x + (isFaceLeft?tank.bulletX:-tank.bulletX);
		this.y = tank.y + tank.bulletY;
		
		this.vX = avX;
		this.vY = avY;
		
		aVX = Math.abs(vX);
		
		double start = -1;
		int i = 0;
		for (int len = angels.size(); i < len; i++) {
			double end = angels.get(i) * aVX; 
			if((start == -1 || vY < start) && vY > end ){
				break;
			}
			start = end;
		}
		cur = i;
		changeAnimation(cur);
		
		live();
	}
	
	public void disappear(){
		this.tank.setShooting(false);
		this.tank.stand();
		
		die();
	}

	public void explode(){
		explode(null);
	}
	
	public void explode(Tank[] targets){
		explode.x = this.x;
		explode.y = this.y;
		
		explode.live();
		disappear();
	}

	public void changeAnimation(int animationNo) {
		this.animationNo = isFaceLeft ? animationNo : animationNo + animLength;
		getCurrentAnim().reset();
	}

	public Tank getTank() {
		return tank;
	}

	public void setTank(Tank tank) {
		this.tank = tank;
	}

	public Explode getExplode() {
		return explode;
	}

	public void setExplode(Explode explode) {
		this.explode = explode;
	}

}
